﻿package com.xm.utils;

import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import com.xm.exceptions.JDBCException;

public class CRUDDAO<T> {
	Connection con;
	ResultSet rt;
	Statement st;
	PreparedStatement pt;
	Class<T> c;

	public CRUDDAO() {

	}

	public CRUDDAO(Class<T> c) {
		this.c = c;
	}

	
	public Map<Integer, List<T>> selectAll(Map<String, Object[]> map) {
		Integer index = 0;
		Map<Integer, List<T>> resultMap = new LinkedHashMap<>();
		List<T> list = new ArrayList<>();
		try {
			con = BaseDao.getConnections();
			if (con != null) {
				Set<Entry<String, Object[]>> entrySet = map.entrySet();
				for (Entry<String, Object[]> entry : entrySet) {
					Object[] value = entry.getValue();
					pt = con.prepareStatement(entry.getKey());
					this.bind(value);
					rt = pt.executeQuery();
					while (rt.next()) {
						list.add(tobean1());
					}
				}
				resultMap.put(index++, list);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			BaseDao.closeAll(con, st, rt);
		}
		return resultMap;
	}

	/**
	 * 根据ResultSet来提取出从数据库得到的数据 并且封装成某一个实体类的类型
	 * @return
	 */
	public T tobean1() {
		T t = null;
		try {
			t = c.newInstance();
			// 通过反射得到你要的类的对象所有属性
			Field[] df = c.getDeclaredFields();
			for (Field field : df) {
				field.setAccessible(true);// 作用就是让我们在用反射时访问私有变量
				Object value = rt.getObject(field.getName());// 返回由此 Field对象表示的字段的名称。
				field.set(t, value);// 将指定对象参数上的此Field对象表示的字段设置为指定的新值。
			}
		} catch (Exception e) {
			e.printStackTrace();
			throw new JDBCException("封装对象异常");
		}
		return t;
	}

	
	public List<Map<String, Object>> selectAll1(Map<String, Object[]> map, Class c1) {
		Integer index = 0;
		List<Map<String, Object>> list = new ArrayList<>();
		try {
			con = BaseDao.getConnections();
			if (con != null) {
				Set<Entry<String, Object[]>> entrySet = map.entrySet();
				for (Entry<String, Object[]> entry : entrySet) {
					Object[] value = entry.getValue();
					pt = con.prepareStatement(entry.getKey());
					this.bind(value);
					rt = pt.executeQuery();
					while (rt.next()) {
						ResultSetMetaData rsmd = (ResultSetMetaData) rt.getMetaData();
						Map<String, Object> resultMap = new LinkedHashMap<>();
						int columnCount = rsmd.getColumnCount();
						for (int i = 0; i < columnCount; i++) {
							resultMap.put(rsmd.getColumnName(i + 1), rt.getObject(i + 1));
						}
						list.add((Map<String, Object>) resultMap);
					}
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			BaseDao.closeAll(con, st, rt);
		}
		return list;
	}

	/**
	 * 查询数据表的记录总数
	 * @param sql
	 * @return
	 */
	public int selectCount(String sql) {
		try {
			con = BaseDao.getConnections();
			if (con != null) {
				pt = con.prepareStatement(sql);
				rt = pt.executeQuery();
				if (rt.next()) {
					return rt.getInt(1);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			BaseDao.closeAll(con, pt, rt);
		}
		return 0;
	}

	/**
	 * 查询数据表的记录总数
	 * @param sql
	 * @return
	 */
	public int selectCount(String sql, Object... obj) {
		try {
			con = BaseDao.getConnections();
			if (con != null) {
				pt = con.prepareStatement(sql);
				this.bind(obj);
				rt = pt.executeQuery();
				if (rt.next()) {
					return rt.getInt(1);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			BaseDao.closeAll(con, pt, rt);
		}
		return 0;
	}
	
	public List<T>  select(String sql,Object ...obj){
		List<T> list=new ArrayList<>();
		try {
			con= BaseDao.getConnections();
			if(con!=null){
				pt= con.prepareStatement(sql);
				bind(obj);
				 rt= pt.executeQuery();
				 while(rt.next()){
					 list.add(tobean());
				 }
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}finally{
			BaseDao.closeAll(con, st, rt);
		}
		return list;
	}

	
	// 查询单个列值
	public Object excuteQueryObject(String sql, Object... objects) {
		Object obj = null;
		con = BaseDao.getConnections();
		try {
			if (con != null) {
				pt = con.prepareStatement(sql);
				this.bind(objects);
				rt = pt.executeQuery();
				if (rt.next()) {
					obj = rt.getObject(1);
				}
			}
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			throw new JDBCException("查询单个列值异常");
		}finally {
			BaseDao.closeAll(con, pt, rt);
		}
		return obj;
	}

	/**
	 * 修改
	 * @param map
	 * @return
	 */
	public int[] updateAll(Map<String, Object[]> map) {
		int error = 0;
		int index = 0;
		int[] row = new int[map.size()];
		try {
			con = BaseDao.getConnections();
			if (con != null) {
				Set<Entry<String, Object[]>> entrySet = map.entrySet();
				// 关闭MySQL的自动提交功能
				con.setAutoCommit(false);
				for (Entry<String, Object[]> entry : entrySet) {
					pt = con.prepareStatement(entry.getKey());
					this.bind(entry.getValue());
					row[index] = pt.executeUpdate();
					/*
					 * if(row[index]==0){ throw new JDBCException("修改失败数据回滚"); }
					 */
					index++;
				}
			} else {
				System.out.println("数据库连接失败！");
			}
		} catch (JDBCException e) {
			System.out.println(e.getMessage());
			error++;
		} catch (Exception e) {
			System.out.println(e.getMessage());
			error++;
		} finally {
			if (error > 0) {
				try {
					// 事务回滚
					con.rollback();
					System.out.println("rollback");
				} catch (SQLException e) {
					e.printStackTrace();
				}
			} else {
				try {
					// 事务提交
					con.commit();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
			BaseDao.closeAll(con, pt, null);

		}
		return row;
	}

	/**
	 * 根据ResultSet来提取出从数据库得到的数据 并且封装成某一个实体类的类型
	 * 
	 * @return
	 */
	private T tobean() {
		T t=null;
		try {
			t=c.newInstance();
			Field[] df = c.getDeclaredFields();
			for (Field field : df) {
				field.setAccessible(true);
				Object value=rt.getObject(field.getName());
				field.set(t, value);
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		return t;
	}

	/**
	 * 绑定参数
	 */
	private void bind(Object[] obj) {
		try {
			if (obj != null && obj.length > 0) {
				for (int i = 0; i < obj.length; i++) {
					pt.setObject(i + 1, obj[i]);
				}
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

	
	
	
	public void name(String cid, Class c) {
		Map<String, Object[]> map = new LinkedHashMap<>();
		map.put("select * from t_category where cid=? ", new Object[] { cid });
		List<Map<String, Object>> selectAll1 = selectAll1(map, c);
		System.out.println("op" + selectAll1);

	}

}
